home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / Pict2Ascii 1.03 / Src / (No AS) / CDocument.cp next >
Encoding:
Text File  |  1997-05-29  |  26.3 KB  |  994 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //    CDocument.cp                                    ©1997 BB's Team inc. All rights reserved
  3. // =================================================================================
  4. #include "PL_Utils.h"
  5. #include "PLConstants.h"
  6. #include "LDynamicPopupMenu.h"
  7. #include "CMemoryIndicator.h"
  8. #include "CGreyCaption.h"
  9. #include "GWorldSaver.h"
  10. #include "CDocument.h"
  11.  
  12. #include <LFile.h>
  13. #include <LPrintout.h>
  14. #include <LPlaceHolder.h>
  15. #include <LString.h>
  16. #include <LWindow.h>
  17. #include <LCaption.h>
  18. #include <LEditField.h>
  19. #include <PP_Messages.h>
  20. #include <PP_KeyCodes.h>
  21. #include <UMemoryMgr.h>
  22. #include <UWindows.h>
  23. #include <UReanimator.h>
  24. #include <UDrawingState.h>
  25. #include <UDesktop.h>
  26. #include <UPrintingMgr.h>
  27.  
  28. #ifdef PL_PROFILE
  29.     #include <UProfiler.h>
  30. #endif
  31.  
  32.  
  33. // ---------------------------------------------------------------------------------
  34. //        • CDocument(LCommander*, FSSpec*, CPreferences*)
  35. // ---------------------------------------------------------------------------------
  36. CDocument::CDocument(
  37.     LCommander        *inSuper,
  38.     FSSpec            *inFileSpec,
  39.     CPreferences    *inPreferences)
  40.         : LSingleDoc (inSuper)
  41.         , mPreferences (inPreferences)
  42. {
  43.     // Create the window and show it
  44.     mWindow = LWindow::CreateWindow (rPPob_MainWindow, this);
  45.     Assert_ (mWindow != nil);
  46.     mWindow->Show();
  47.  
  48.     // Keep easy access to important Panes
  49.     mDynamicText = (CDynamicText*) mWindow -> FindPaneByID (kDynamicText);
  50.     Assert_ (mDynamicText != nil);
  51.  
  52.     mShowPane = (CGWorldPane*) mWindow -> FindPaneByID (kShowPane);
  53.     Assert_ (mShowPane != nil);
  54.  
  55.     //
  56.     // If the prefs are read from the prefs file, we initialize with them.
  57.     // if they're not, we initialize THEM with the default values set in
  58.     // the interface definition (Constructor PPob).
  59.     // We must set take care with buttons in radio groups, because only value
  60.     // Button_On makes them broadcast to the radio group to set off the others.
  61.  
  62.     // text traits
  63.     if ( mPreferences->IsOk() ) {
  64.         mPreferences->GetTextTraits (mTextTraits);
  65.         mDynamicText->SetTextTraits (mTextTraits);
  66.     }
  67.     else {
  68.         mDynamicText->GetTextTraits (mTextTraits);
  69.         mPreferences->SetTextTraits (mTextTraits);
  70.     }
  71.     mFontLight.SetTextTraits (mTextTraits);
  72.     mImageLight.SetTextTraits (mTextTraits);
  73.  
  74.     // optimize for screen / printer
  75.     if ( mPreferences->IsOk() )
  76.         if ( mPreferences->GetScreen() )
  77.             mWindow->SetValueForPaneID (kScreenButton, Button_On);
  78.         else
  79.             mWindow->SetValueForPaneID (kPrinterButton, Button_On);
  80.     else
  81.         mPreferences->SetScreen ( mWindow->GetValueForPaneID(kScreenButton) );
  82.     mFontLight.SetScreen (mPreferences->GetScreen());
  83.  
  84.     // Ascii 7/8 bits
  85.     if ( mPreferences->IsOk() )
  86.         if ( mPreferences->Get7Bits() )
  87.             mWindow->SetValueForPaneID (k7bitsButton, Button_On);
  88.         else
  89.             mWindow->SetValueForPaneID (k8bitsButton, Button_On);
  90.     else
  91.         mPreferences->Set7Bits ( mWindow->GetValueForPaneID (k7bitsButton) );
  92.     mFontLight.Set7Bits  (mPreferences->Get7Bits());
  93.  
  94.     // AutoContrast on/off
  95.     if ( mPreferences->IsOk() )
  96.         mWindow->SetValueForPaneID (kContrastCheck, mPreferences->GetContrast() );
  97.     else
  98.         mPreferences->SetContrast (mWindow->GetValueForPaneID(kContrastCheck) );
  99.     mGenText.SetContrast (mPreferences->GetContrast());
  100.  
  101.     //
  102.     // Initialize controls that are not in the window but in the prefs dialog
  103.     // The prefs ctor provides values for these ones
  104.     //
  105.     // mMonoSpace            global to all documents
  106.     // mConfirmPrinting    idem
  107.     // mBeep32k                idem
  108.     mFontLight.SetAllowed ( mPreferences->GetAllowed() );
  109.  
  110.     // This is too dangerous to save in prefs.
  111.     // We take it from the PPob
  112.     // I'll add a "default zoom" field in the preferences… in  another life.
  113.     mRatio = mWindow->GetValueForPaneID (kRatioEditField);
  114.  
  115.     // Set the area used to compute the font lightness
  116.     // We use the frame of the ShowPane… why not ?!
  117.     Rect theFrame;
  118.     mShowPane->CalcLocalFrameRect (theFrame);
  119.     mFontLight.SetRect (theFrame);
  120.  
  121.     // we don't allow normal events processing while computing…
  122.     mWindow->UpdatePort();
  123.  
  124.     // Initialize font and size popups
  125.     SetupControls ();
  126.     
  127.     // NOW we can add self as listener to all controls in the Window
  128.     // (no need for StopListening() and StartListening() to avoid unnecessary messages)
  129.     UReanimator::LinkListenerToControls (this, mWindow, rRidL_MainWindow);
  130.  
  131.     // we don't allow normal events processing while computing…
  132.     mWindow->UpdatePort();
  133.  
  134.     // Finally open the file
  135.     if ( OpenFile (*inFileSpec) )
  136.         SetModified (true);
  137. }
  138.  
  139.  
  140. // ---------------------------------------------------------------------------------
  141. //        • ~CDocument
  142. // ---------------------------------------------------------------------------------
  143. CDocument::~CDocument()
  144. {}
  145.  
  146.  
  147. // ---------------------------------------------------------------------------------
  148. //        • HandleKeyPress
  149. // ---------------------------------------------------------------------------------
  150. Boolean CDocument::HandleKeyPress (const EventRecord &inKeyEvent)
  151. {
  152.     Int16        theKey = inKeyEvent.message & charCodeMask;
  153.  
  154.     if ( theKey==char_Enter || theKey==char_Return) {
  155.  
  156.         LEditField *theField = (LEditField*) mWindow->FindPaneByID (kRatioEditField);
  157.         Assert_ (theField != nil);
  158.  
  159.         Int32        theRatio;
  160.         theRatio = theField->GetValue();
  161.  
  162.         if ( theRatio!=mRatio ) {
  163.  
  164.             Int32    saveRatio = mRatio;
  165.             mRatio=theRatio;
  166.             ReadPictFile();
  167.         }
  168.         return true;
  169.  
  170.     }
  171.     else
  172.         return LCommander::HandleKeyPress(inKeyEvent);
  173. }
  174.  
  175.  
  176. // ---------------------------------------------------------------------------------
  177. //        • SetupControls
  178. // ---------------------------------------------------------------------------------
  179. void CDocument::SetupControls (void)
  180. {
  181.     // Avoid too many messages while building
  182.     StopListening();
  183.  
  184. #ifdef powerc
  185.     SetStatus (nil);
  186. #endif
  187.  
  188.     //
  189.     // Font popup
  190.     //
  191.     
  192.     // Get the font popup.
  193.     LDynamicPopupMenu    *thePopup;
  194.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kFontPopup );
  195.     Assert_( thePopup != nil );
  196.     
  197.     Int16        theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  198.     Str255    theMenuText;
  199.  
  200.     // Eliminate non-mono-space fonts if so the user desires
  201.     if ( mPreferences->GetMonoSpace() )
  202.         for ( Int16 i=theCount; i>0; --i ) {
  203.  
  204.             ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  205.  
  206.             // update user info
  207.             LStr255 theText (rSTR, kCheckingMonoSpace);
  208.             theText.Append (theMenuText);
  209.             SetStatus (theText);
  210.             
  211.             if ( ::CompareString( mTextTraits.fontName, theMenuText, nil ) == 0 ) {
  212.                 // this is the one we want to set the popup to, don't delete !
  213.             }
  214.             else     if ( !PL_Utils::IsMonoSpace (theMenuText) )
  215.                 ::DeleteMenuItem (thePopup->GetMacMenuH(), i);
  216.         }
  217.  
  218.     // Reset the popup value
  219.     theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  220.     for ( Int16 i=1 ; i<=theCount ; ++i ) {
  221.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  222.         if ( ::CompareString( mTextTraits.fontName, theMenuText, nil ) == 0 ) {
  223.             thePopup->FinishedCreatingMenu (i);
  224.             break;
  225.         }
  226.     }
  227.     thePopup->Refresh();
  228.     
  229.     //
  230.     // Size popup
  231.     //
  232.  
  233.     // Get the size popup.
  234.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID ( kSizePopup );
  235.     Assert_( thePopup != nil );
  236.     
  237.     // Get the number of items in the menu (-2 for the 'Other…' item)
  238.     theCount = -2 + ::CountMenuItems( thePopup->GetMacMenuH() );
  239.  
  240.     // Set the popup value (assumes our size is in the popup !)
  241.     for ( Int16 i=1; i<=theCount; ++i ) {
  242.     
  243.         // Get the menu item text.
  244.         Str255    theMenuText;
  245.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  246.  
  247.         // Get the size referred to by the menu item.
  248.         Int32    theSize;
  249.         ::StringToNum( theMenuText, &theSize );
  250.  
  251.         if ( mTextTraits.size == theSize ) {
  252.         
  253.             // Set the value for the popup.
  254.             thePopup->FinishedCreatingMenu (i);
  255.             break;
  256.             
  257.         }
  258.     }
  259.     
  260.     // Adjust the size menu styles (bold where IM says it should)
  261.     AdjustSizeMenuForFont (mTextTraits.fontNumber);
  262.  
  263.     // Start listening again.            
  264.     StartListening();
  265. }
  266.  
  267.  
  268. // ---------------------------------------------------------------------------------
  269. //        • SetName
  270. // ---------------------------------------------------------------------------------
  271. void
  272. CDocument::SetName (Str63 inName)
  273. {
  274.     LStr255 name (inName);
  275.     LStr255 up (name);
  276.     ::UppercaseText((Ptr) &up[1], up[0], smSystemScript);
  277.     if (up.EndsWith ("PICT", 4) )
  278.         name.Replace (name.Length()-3, 4, "txt", 3);
  279.     else
  280.         name.Append (".txt",4);
  281.     
  282.     mWindow->SetDescriptor (name);
  283. }
  284.  
  285.  
  286. // ---------------------------------------------------------------------------------
  287. //        • OpenFile
  288. // ---------------------------------------------------------------------------------
  289. Boolean
  290. CDocument::OpenFile(
  291.     FSSpec    &inFileSpec )
  292. {
  293.     OSErr    err;
  294.  
  295.     // Create a new file object & open the data fork.
  296.     mFile = new LFile (inFileSpec);
  297.  
  298.     // Read the Pict, create an offscreen copy
  299.     err = ReadPictFile();
  300.  
  301.     // Set window title acording to the name of the file.
  302.     SetName (inFileSpec.name);
  303.  
  304.     // Flag that document has an associated file (not in this particular case !)
  305.     mIsSpecified = false;
  306.  
  307.     return (err==noErr);    
  308. }
  309.  
  310.  
  311. // ---------------------------------------------------------------------------------
  312. //        • ReadPictFile
  313. // ---------------------------------------------------------------------------------
  314. OSErr CDocument::ReadPictFile (void)
  315. {
  316.     OSErr    err;
  317.     
  318.     SetStatus (rSTR, kReadingPictFile);
  319.  
  320.     // Ask for room : they will change anyway
  321.     mImageLight.MakeRoom (true);        // light buffer : 1 float per text char
  322.     mGenText.MakeRoom ();                // text buffer  : 1 char per char
  323.     SetTextStr ("\p");                    // TE record    : idem, limited to 32k
  324.     mGreyPict.MakeRoom ();                // offscreen grey picture
  325.  
  326.     Int16 theDataFork;
  327.     theDataFork = mFile->OpenDataFork (fsRdWrPerm);
  328.     
  329. Try_ {
  330.  
  331.     // Read the Pict file into a Handle
  332.     Int32    fileLength;
  333.     err = ::GetEOF(theDataFork, &fileLength);
  334.     ThrowIfOSErr_(err);
  335.     
  336.     fileLength -= kPICTHeaderSize;
  337.  
  338.     // throws if mem fails.
  339.     // uses temp mem if not enough in core
  340.     // dtor is called if an exception is thrown
  341.     StHandleBlock thePict (fileLength, true, true);
  342.  
  343.     err = ::SetFPos(theDataFork, fsFromStart, kPICTHeaderSize);
  344.     ThrowIfOSErr_(err);
  345.  
  346.     err = ::FSRead(theDataFork, &fileLength, *(Handle)thePict);
  347.     ThrowIfOSErr_(err);
  348.  
  349.     mFile->CloseDataFork();
  350.     
  351.     // Finish creation of mGrey
  352.     Rect    offRect;
  353.     offRect = (**(PicHandle)(Handle)thePict).picFrame;    // (Handle) accessor, not PicHandle…
  354.     ::OffsetRect (&offRect, -offRect.left, -offRect.top);
  355.     offRect.right  *= mRatio/100.;
  356.     offRect.bottom *= mRatio/100.;
  357.  
  358.     // the real allocation happens here
  359.     mGreyPict.SetRect (offRect);
  360.  
  361.     // Copy the picture to offscreen
  362.     if ( mGreyPict.IsOK() ) {
  363.         GWorldSaver saveGW (mGreyPict);    
  364.         mGreyPict.Lock();
  365.         ::EraseRect ( &offRect );    
  366.         StColorState::Normalize();
  367.         ::DrawPicture ((PicHandle)(Handle)thePict, &offRect);
  368.         mGreyPict.Unlock();
  369.     }
  370.  
  371.     // dtor does ::DisposeHandle ((Handle)thePict);
  372. }
  373.  
  374. Catch_ (inErr) {
  375. } EndCatch_
  376.  
  377.     // erase message bar
  378.     SetStatus();
  379.     
  380.     // Tell'em we changed
  381.     mShowPane->SetGWorld (mGreyPict);
  382.     mImageLight.SetGreyWorld (&mGreyPict);
  383.     SetModified (true);
  384.     Compute();
  385.     
  386.     return err;
  387. }
  388.  
  389.  
  390. // ---------------------------------------------------------------------------------
  391. //        • DoAESave
  392. // ---------------------------------------------------------------------------------
  393. void
  394. CDocument::DoAESave(
  395.     FSSpec    &inFileSpec,
  396.     OSType    inFileType )
  397. {
  398.     // Delete the existing file object.
  399.     delete mFile;
  400.     
  401.     // Make a new file object.
  402.     mFile = new LFile (inFileSpec);
  403.     
  404.     // Get the proper file type.
  405.     OSType theFileType = 'TEXT';
  406.     if (inFileType !=fileType_Default)
  407.         theFileType = inFileType;
  408.  
  409.     // Make new file on disk
  410.     mFile->CreateNewDataFile ('CWIE', theFileType);    
  411.  
  412.     // Write out the data.
  413.     DoSave();
  414.  
  415.     // Change window title to reflect the new name.
  416.     mWindow->SetDescriptor (inFileSpec.name);
  417.  
  418.     // Document now has a specified file.
  419.     mIsSpecified = true;
  420. }
  421.  
  422.  
  423. // ---------------------------------------------------------------------------------
  424. //        • FindCommandStatus
  425. // ---------------------------------------------------------------------------------
  426. void
  427. CDocument::FindCommandStatus(
  428.     CommandT    inCommand,
  429.     Boolean        &outEnabled,
  430.     Boolean        &outUsesMark,
  431.     Char16        &outMark,
  432.     Str255        outName )
  433. {
  434.     switch ( inCommand ) {
  435.  
  436.         default:
  437.         {
  438.             // Call inherited.
  439.             LSingleDoc::FindCommandStatus( inCommand,
  440.                 outEnabled, outUsesMark, outMark, outName );
  441.         }
  442.         break;
  443.  
  444.     }
  445. }
  446.  
  447.  
  448. // ---------------------------------------------------------------------------
  449. //        • ObeyCommand
  450. // ---------------------------------------------------------------------------
  451. Boolean CDocument::ObeyCommand (
  452.     CommandT    inCommand,
  453.     void        *ioParam)
  454. {
  455.     Boolean        cmdHandled = true;
  456.  
  457.     switch (inCommand) {
  458.     
  459.         case cmd_PageSetup:
  460.             SetupPage();
  461.             break;
  462.             
  463.         case cmd_Preferences:
  464.             LStr255 allowed ( mFontLight.GetAllowed() );
  465.             mPreferences->DoDialog (allowed, mTextTraits.fontName);
  466.             if ( allowed != mPreferences->GetAllowed() ) {
  467.                 mFontLight.SetAllowed ( mPreferences->GetAllowed() );
  468.                 Compute ();
  469.             }
  470.             break;
  471.             
  472.         default:
  473.             cmdHandled = LSingleDoc::ObeyCommand(inCommand, ioParam);
  474.             break;
  475.     }
  476.     
  477.     return cmdHandled;
  478. }
  479.  
  480.  
  481. // ---------------------------------------------------------------------------------
  482. //        • AdjustSizeMenuForFont
  483. // ---------------------------------------------------------------------------------
  484. void
  485. CDocument::AdjustSizeMenuForFont (Int16 inFontNumber)
  486. {
  487.     // Get the size popup.
  488.     LDynamicPopupMenu    *thePopup;
  489.     thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kSizePopup );
  490.     Assert_( thePopup != nil );
  491.     
  492.     // Get the number of items in the menu.
  493.     Int16    theCount = ::CountMenuItems( thePopup->GetMacMenuH() );
  494.     
  495.     for ( Int16 i=1; i<=theCount -2 /* Other... */ ; ++i ) {
  496.     
  497.         // Get the menu item text.
  498.         Str255    theMenuText;
  499.         ::GetMenuItemText( thePopup->GetMacMenuH(), i, theMenuText );
  500.         
  501.         // Get the size referred to by the menu item.
  502.         Int32    theSize;
  503.         ::StringToNum( theMenuText, &theSize );
  504.         
  505.         // Set the item style.
  506.         ::SetItemStyle( thePopup->GetMacMenuH(), i,
  507.             ::RealFont( inFontNumber, theSize ) ? bold : normal );
  508.     }
  509.     
  510.     // Refresh the popup.
  511.     thePopup->Refresh();
  512. }
  513.  
  514.  
  515. // ---------------------------------------------------------------------------------
  516. //        • DoSave
  517. // ---------------------------------------------------------------------------------
  518. void
  519. CDocument::DoSave()
  520. {
  521.     // Open the data fork.
  522.     mFile->OpenDataFork (fsRdWrPerm);
  523.  
  524.     // the GenText may contain a nil Text. A user should not ask
  525.     // for saving in such circumstances, but you never know...
  526.     Handle theTextH;
  527.     
  528.     theTextH = mGenText.GetText();
  529.     if ( theTextH==nil )
  530.         theTextH = mDynamicText->GetTextHandle();
  531.         
  532.     // Lock the text handle (locally)
  533.     StHandleLocker theLock (theTextH);
  534.  
  535.     // Write the text to the file.
  536.     mFile->WriteDataFork (*theTextH, ::GetHandleSize (theTextH));
  537.  
  538.     // Close the data fork.
  539.     mFile->CloseDataFork();
  540.  
  541.     // Saving makes doc un-dirty.
  542.     SetModified (false);
  543. }
  544.  
  545.  
  546. // ---------------------------------------------------------------------------------
  547. //        • ListenToMessage
  548. // ---------------------------------------------------------------------------------
  549. void
  550. CDocument::ListenToMessage (MessageT inMessage, void *ioParam)
  551. {
  552.     switch ( inMessage ) {
  553.     
  554.         case msg_FontPopup:
  555.         {
  556.             // Get the font popup.
  557.             LDynamicPopupMenu    *thePopup;
  558.             thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID ( kFontPopup );
  559.             Assert_( thePopup != nil );
  560.  
  561.             // Get the menu item text. The value of the popup
  562.             // is passed in ioParam (it's a long integer).
  563.             ::GetMenuItemText( thePopup->GetMacMenuH(),
  564.                 *(Int32 *)ioParam, mTextTraits.fontName );
  565.  
  566.             // Get the font number.
  567.             ::GetFNum( mTextTraits.fontName, &mTextTraits.fontNumber );
  568.             
  569.             // Adjust the size menu styles.
  570.             AdjustSizeMenuForFont ( mTextTraits.fontNumber );
  571.             
  572.             // compute text with the new font and refresh view
  573.             mFontLight.SetTextTraits (mTextTraits);
  574.             mImageLight.SetTextTraits (mTextTraits);
  575.             Compute();
  576.             mPreferences->SetTextTraits (mTextTraits);
  577.         }
  578.         break;
  579.         
  580.         case msg_SizePopup:
  581.         {
  582.             // Get the size popup.
  583.             LDynamicPopupMenu    *thePopup;
  584.             thePopup = (LDynamicPopupMenu *) mWindow->FindPaneByID( kSizePopup );
  585.             Assert_( thePopup != nil );
  586.  
  587.             // Get the menu item text. The value of the popup
  588.             // is passed in ioParam (it's a long integer).
  589.             Str255    theMenuText;
  590.             ::GetMenuItemText( thePopup->GetMacMenuH(),
  591.                 *(Int32 *)ioParam, theMenuText );
  592.  
  593.             // Get the size referred to by the menu item.
  594.             Int32    theSize;
  595.             ::StringToNum( theMenuText, &theSize );
  596.  
  597.             // Set the size in the text traits.
  598.             mTextTraits.size = theSize;
  599.  
  600.             // compute text with the new font and refresh view
  601.             mFontLight.SetTextTraits (mTextTraits);
  602.             mImageLight.SetTextTraits (mTextTraits);
  603.             Compute();
  604.             mPreferences->SetTextTraits (mTextTraits);
  605.         }
  606.         break;
  607.         
  608.         case msg_ContrastCheck:
  609.         {
  610.             mGenText.SetContrast (*(Int32 *)ioParam==Button_On);
  611.             Compute();
  612.             mPreferences->SetContrast (*(Int32 *)ioParam==Button_On);
  613.         }
  614.         break;
  615.  
  616.         case msg_ControlClicked:
  617.         {
  618.             PaneIDT    thePaneID = ((LPane*)ioParam)->GetPaneID();
  619.             switch ( thePaneID) {
  620.                 case kScreenButton :
  621.                 case kPrinterButton :
  622.                     mFontLight.SetScreen        ( thePaneID==kScreenButton );
  623.                     mPreferences->SetScreen    ( thePaneID==kScreenButton );
  624.                     break;
  625.                 case k7bitsButton :
  626.                 case k8bitsButton :
  627.                     mFontLight.Set7Bits        ( thePaneID==k7bitsButton );
  628.                     mPreferences->Set7Bits    ( thePaneID==k7bitsButton );
  629.                     break;
  630.                 default :
  631.                     SysBeep (1);
  632.             }
  633.             Compute();
  634.         }
  635.         break;
  636.  
  637.         default:
  638.         {
  639.         }
  640.     }
  641. }
  642.  
  643.  
  644. // ---------------------------------------------------------------------------------
  645. //        • Compute
  646. // ---------------------------------------------------------------------------------
  647. void
  648. CDocument::Compute (void)
  649. {
  650.  
  651. #ifdef PL_PROFILE
  652. //    StProfileSection profile ("\pProfile", 4000, 50);
  653. #endif
  654.  
  655.     // Reset the col and row info
  656.     ClearInfo();
  657.  
  658.     // Reading Pict failed
  659.     if ( !mGreyPict.IsOK() ) {
  660.         SetTextStr (rSTR, kNoMemForPict);
  661.         return;
  662.     }
  663.     
  664.     // Update the FontLight
  665.     if (!mFontLight.IsUpToDate() ) {
  666.         mGenText.MakeRoom();
  667.         SetStatus (rSTR, kComputingFontLight);
  668.         mFontLight.Update ();
  669.         SetStatus ();
  670.     }
  671.  
  672.     // Still not UpToDate if a pb occured
  673.     if (!mFontLight.IsUpToDate() ) {
  674.         SetTextStr (rSTR, kNoMemForFont);
  675.         return;
  676.     }
  677.  
  678.     // Update the col and row info
  679.     UpdateInfo();
  680.     
  681.     // if the 32k limit is exceeded, tell the user
  682.     if ( mImageLight.GetTextSize() > 32000 )
  683.         if ( ! mPreferences->GetBeep32k() )
  684.             mPreferences->SetBeep32k (! TellOverflow());
  685.         else
  686.             SysBeep(1);
  687.     
  688.     // Update the ImageLight
  689.     if (!mImageLight.IsUpToDate() ) {
  690.         mGenText.MakeRoom();
  691.         SetStatus (rSTR, kComputingImageLight);
  692.         mImageLight.Update ();
  693.         SetStatus ();
  694.     }
  695.  
  696.     // Check we can go on
  697.     if ( mImageLight.GetLight()==nil ) {
  698.         SetTextStr (rSTR, kNoMemForPictLight);
  699.         return;
  700.     }
  701.     
  702.     // Update the GenText
  703.     SetStatus (rSTR, kComputingText);
  704.     mGenText.Update (mFontLight, mImageLight);
  705.     SetStatus ();
  706.     if (mGenText.GetText()==nil) {
  707.         SetTextStr (rSTR, kNoMemForText);
  708.         return;
  709.     }
  710.     SetModified (true);
  711.  
  712.     // Warning : do not invert SetWidth and SetTextPtr. I spent 2 hours on this one...
  713.     mDynamicText->SetTextTraits (mTextTraits);
  714.  
  715.     // Why 40 ? Better for some non-monospace fonts… but not enough
  716.     // for some other. Ought to be 1 or 2 if everything went fine.
  717.     mDynamicText->SetWidth ( mImageLight.GetPictWidth() + 40 );
  718.     
  719.     Handle theText = mGenText.GetText();
  720.     StHandleLocker theLock(theText);
  721.  
  722.     Int32 theSize;
  723.     theSize = mImageLight.GetTextSize();
  724.     if (theSize > 32000 )
  725.         theSize = 32000;
  726.  
  727.     mDynamicText->SetTextPtr ( (Ptr)(*theText), theSize );
  728.  
  729.     // Update the number of pages
  730.     UpdatePagesNumber();
  731. }
  732.  
  733.  
  734.  
  735. // ---------------------------------------------------------------------------------
  736. //        • UpdateInfo
  737. // ---------------------------------------------------------------------------------
  738. void CDocument::ClearInfo (void)
  739. {
  740.     mWindow->SetDescriptorForPaneID( kLinesCaption  , "\p" );
  741.     mWindow->SetDescriptorForPaneID( kColumnsCaption, "\p" );
  742.     mWindow->SetDescriptorForPaneID( kPagesCaption  , "\p" );
  743. }
  744.  
  745.  
  746. // ---------------------------------------------------------------------------------
  747. //        • UpdateInfo
  748. // ---------------------------------------------------------------------------------
  749. void CDocument::UpdateInfo (void)
  750. {
  751.     // Tell the size in line && column units
  752.     LStr255    theLStr;
  753.     Str255    theStr;
  754.     
  755.     theLStr  = mImageLight.GetHeightN();
  756.     GetIndString (theStr, rSTR, kLines);
  757.     theLStr += theStr;
  758.     mWindow->SetDescriptorForPaneID( kLinesCaption, theLStr );
  759.     
  760.     theLStr  = mImageLight.GetWidthN();
  761.     GetIndString (theStr, rSTR, kColumns);
  762.     theLStr += theStr;
  763.     mWindow->SetDescriptorForPaneID( kColumnsCaption, theLStr );
  764. }
  765.  
  766.  
  767. // ---------------------------------------------------------------------------------
  768. //        • UpdatePagesNumber
  769. // ---------------------------------------------------------------------------------
  770. void CDocument::UpdatePagesNumber (void)
  771. {
  772.     // Tell the size in pages, between parenthesis if partial (>32k)
  773.     LStr255    theLStr;
  774.     Str255    theStr;
  775.     Int32 thePages;
  776.     
  777.     thePages = DoMaybePrint (false);
  778.     if (thePages>0) {
  779.         theLStr  = thePages;
  780.         GetIndString (theStr, rSTR, kPages);
  781.         theLStr += theStr;
  782.         if (thePages>1)
  783.             theLStr += "\ps";
  784.         if ( mImageLight.GetTextSize() > 32000 )
  785.             theLStr  = "\p(" + theLStr + "\p)";
  786.         mWindow->SetDescriptorForPaneID( kPagesCaption, theLStr );
  787.     }
  788. }
  789.  
  790.  
  791.  
  792. // ---------------------------------------------------------------------------------
  793. //        • TellOverflow
  794. // ---------------------------------------------------------------------------------
  795. Boolean CDocument::TellOverflow (void)
  796. {
  797.         UDesktop::Deactivate();
  798.         Int16 answer = ::CautionAlert(ALRT_TellOverflow, nil);
  799.         UDesktop::Activate();
  800.         return answer==kButtonOk;
  801. }
  802.  
  803.  
  804. // ---------------------------------------------------------------------------------
  805. //        • SetStatus
  806. // ---------------------------------------------------------------------------------
  807. void CDocument::SetStatus (
  808.     ConstStringPtr    inDescriptor)
  809. {
  810.     // Update the status line
  811.     CGreyCaption *theCaption;
  812.     theCaption = (CGreyCaption*) mWindow -> FindPaneByID (kGreyCaption);
  813.     Assert_ (theCaption != nil);
  814.  
  815.     if (inDescriptor != nil)
  816.         theCaption->SetDescriptor (inDescriptor);    // (auto refresh)
  817.  
  818.     // Also update the memory indicator (no event loop at startup…)
  819.     CMemoryIndicator *theMemo;
  820.     theMemo = (CMemoryIndicator*) mWindow -> FindPaneByID (kMemoryIndicator);
  821.     Assert_ (theMemo != nil);
  822.     theMemo->SpendTime();        // (auto refresh)
  823. }
  824.  
  825.  
  826. // ---------------------------------------------------------------------------------
  827. //        • SetStatus
  828. // ---------------------------------------------------------------------------------
  829. void CDocument::SetStatus (
  830.     ResIDT    inSTR,
  831.     Int16        inIndex)
  832. {
  833.     LStr255    theMessage (inSTR, inIndex);
  834.     SetStatus (theMessage);
  835. }
  836.  
  837.  
  838. // ---------------------------------------------------------------------------------
  839. //        • SetTextStr
  840. // ---------------------------------------------------------------------------------
  841. void CDocument::SetTextStr (
  842.     ConstStringPtr    inMsg)
  843. {
  844.     TextTraitsRecord theTextTraits;
  845.     UTextTraits::LoadSystemTraits (theTextTraits);
  846.     mDynamicText->SetTextTraits (theTextTraits);
  847.     mDynamicText->SetTextPtr ((Ptr)&inMsg[1], inMsg[0]);
  848. }
  849.  
  850.  
  851. // ---------------------------------------------------------------------------------
  852. //        • SetTextStr
  853. // ---------------------------------------------------------------------------------
  854. void CDocument::SetTextStr (
  855.     ResIDT    inSTR,
  856.     Int16        inIndex)
  857. {
  858.     Str255    theText;
  859.     GetIndString (theText, inSTR, inIndex);
  860.     SetTextStr (theText);
  861. }
  862.  
  863.  
  864. // ---------------------------------------------------------------------------------
  865. //        • SetupPage
  866. // ---------------------------------------------------------------------------------
  867. void CDocument::SetupPage()
  868. {
  869.     UDesktop::Deactivate();
  870.  
  871.     if (!mPrintRecordH)
  872.         mPrintRecordH = UPrintingMgr::CreatePrintRecord();
  873.  
  874.     if (mPrintRecordH)
  875.         UPrintingMgr::AskPageSetup (mPrintRecordH);
  876.  
  877.     UDesktop::Activate();
  878.     
  879.     // the number of pages might have changed
  880.     UpdatePagesNumber();
  881. }
  882.  
  883.  
  884. // ---------------------------------------------------------------------------------
  885. //        • DoPrint
  886. // ---------------------------------------------------------------------------------
  887. void CDocument::DoPrint()
  888. {
  889.     DoMaybePrint (true);
  890. }
  891.  
  892.  
  893. // ---------------------------------------------------------------------------------
  894. //        • DoMaybePrint
  895. // ---------------------------------------------------------------------------------
  896. Int16 CDocument::DoMaybePrint (Boolean doIt)
  897. {
  898.     // Create the printout.
  899.     LPrintout *thePrintout = LPrintout::CreatePrintout (rPPob_Printout);
  900.     if (thePrintout==nil)
  901.         return -1;
  902.  
  903.     // Set the print record.
  904.     if (mPrintRecordH)
  905.         thePrintout->SetPrintRecord (mPrintRecordH);
  906.  
  907.     // Get the text PlaceHolder.
  908.     LPlaceHolder *thePlaceHolder = (LPlaceHolder*) thePrintout->FindPaneByID (kPlaceHolder);
  909.     Assert_ (thePlaceHolder!=nil);
  910.  
  911.     // Save the text frame, and set it to the text image
  912.     // PlaceHolders are based on frames dimensions, we need images dimensions
  913.     // and PlaceHolder::InstallOccupant is not virtual...
  914.     mDynamicText->PrepareToPrint();
  915.  
  916.     // Center only if the text fits on one page
  917.     SDimension16    thePlaceSize, theTextSize;
  918.     Int16                theAlignment = kAlignAbsoluteCenter;
  919.  
  920.     thePlaceHolder->GetFrameSize (thePlaceSize);
  921.     mDynamicText  ->GetFrameSize (theTextSize);
  922.     if (   thePlaceSize.width  < theTextSize.width
  923.         || thePlaceSize.height < theTextSize.height )
  924.         theAlignment = kAlignNone;
  925.     
  926.     // Install the text view in the PlaceHolder
  927.     thePlaceHolder->InstallOccupant (mDynamicText, theAlignment);
  928.     
  929.     // Count pages
  930.     UInt32 HPage, VPage;
  931.     thePrintout->CountPanels (HPage, VPage);
  932.  
  933.     if ( HPage*VPage > 1 ) {
  934.         
  935.         // Synchronize the PlaceHolder with the  characters dimensions.
  936.         // (The CDocument knows we are in fixed width, not the CDynamicText)
  937.         SetPrintFrameSize (thePlaceHolder);
  938.  
  939.         // ask confirmation if needed
  940.         if ( doIt && mPreferences->GetPrintConfirm() ) {
  941.  
  942.             LStr255 theStr;
  943.             theStr  = (Int32)(HPage*VPage);
  944.  
  945.             ParamText (theStr, "\p", "\p", "\p");
  946.             UDesktop::Deactivate();
  947.             Int16 answer = ::CautionAlert(ALRT_ConfirmPrinting, nil);
  948.             UDesktop::Activate();
  949.         
  950.             if ( answer==kButtonCancel )
  951.                 doIt = false;
  952.         }
  953.     }
  954.     
  955.     // Print.
  956.     if (doIt)
  957.         thePrintout->DoPrintJob();
  958.     
  959.     // Delete the printout.
  960.     delete thePrintout;
  961.     mDynamicText->RevertFromPrint();
  962.     
  963.     return HPage*VPage;
  964. }
  965.  
  966.  
  967. // ---------------------------------------------------------------------------------
  968. //        • SetPrintFrameSize
  969. // ---------------------------------------------------------------------------------
  970. void
  971. CDocument::SetPrintFrameSize (LPlaceHolder* inPlace)
  972. {
  973.     // Get the frame size.
  974.     SDimension16    theFrameSize;
  975.     inPlace->GetFrameSize (theFrameSize);
  976.     
  977.     // Get the text edit record handle.
  978.     TEHandle    theTextEditH = mDynamicText->GetMacTEH();
  979.     
  980.     // Calculate the number of lines per page.
  981.     Int16    theLinesPerPage;
  982.     theLinesPerPage = theFrameSize.height / (**theTextEditH).lineHeight;
  983.  
  984.     // Calculate the number of chars per line
  985.     Int16 theCharsPerLine;
  986.     theCharsPerLine = theFrameSize.width/mImageLight.GetWidth();
  987.     
  988.     // Resize the frame to an integral number of lines/chars.
  989.     inPlace->ResizeFrameTo (
  990.         mImageLight.GetWidth() * theCharsPerLine+1,
  991.         (**theTextEditH).lineHeight * theLinesPerPage,
  992.         false );
  993. }
  994.